<!DOCTYPE html><!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]--><!--[if gt IE 8]><!--><html class="no-js" lang="en"><!--<![endif]--><head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <title></title>
  

  
  <link href="https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Slab:400,700|Inconsolata:400,700" rel="stylesheet" type="text/css">

  <link rel="stylesheet" href="/v2/css/theme.css" type="text/css">
  <link href="/v2/css/custom.css" rel="stylesheet">

  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
  <script src="../../js/theme.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js"></script>
  <script src="../../search/main.js"></script>

  <style>
    body {font-size: 90%;}
    pre, code {font-size: 100%;}
    h3, h4, h5, h6 {color: #2980b9; font-weight: 300}
  </style> 
<meta name="robots" content="noindex"></head>

<body class="wy-body-for-nav" role="document">

  <div class="wy-grid-for-nav">

    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
      <div class="wy-side-nav-search">
        <a href="/v2/" class="icon icon-home"> </a>
        <div role="search">
  <form id="rtd-search-form" class="wy-form" action="" method="get">
    <input type="text" name="q" placeholder="Search docs">
    <input type="hidden" name="check_keywords" value="yes">
    <input type="hidden" name="area" value="default">
  </form>
</div>
      </div>

      <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
      <ul class="current">
   
  <span class="toctree-l0">Home</span>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/">Welcome</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/imprint/">Imprint</a>
    
  </li>
     
  <span class="toctree-l0">Articles</span>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/articles/getting-started/">Getting started</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/articles/heroku/">Heroku</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/articles/express/">Usage with Express.JS</a>
    
  </li>
     
  <span class="toctree-l0">Docs</span>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/docs/installation/">Installation</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/docs/usage/">Usage</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/docs/promises/">Promises</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/docs/models/">Models</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/docs/instances/">Instances</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/docs/associations/">Associations</a>
    
  </li>
  
  <li class="toctree-l1 current">
    <a class="current" href="/v2/docs/hooks/">Hooks</a>
    
    <ul>
      
    </ul>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/docs/transactions/">Transactions</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/docs/migrations/">Migrations</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/docs/misc/">Misc</a>
    
  </li>
     
  <span class="toctree-l0">API</span>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/api/sequelize/">Sequelize</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/api/model/">Model</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/api/instance/">Instance</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/api/associations/">Associations</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/api/hooks/">Hooks</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/api/promise/">Promise</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/api/transaction/">Transaction</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/api/datatypes/">Datatypes</a>
    
  </li>
  
  <li class="toctree-l1 ">
    <a class="" href="/v2/api/errors/">Errors</a>
    
  </li>
    
</ul>
      </div>
      &nbsp;
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" role="navigation" aria-label="top navigation">
        <i data-toggle="wy-nav-top" class="icon icon-reorder"></i>
        <a href="/v2/"></a>
      </nav>

      
      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
    <li><a href="/v2/">Docs</a> »</li>
    <li>Hooks</li>
      <li class="wy-breadcrumbs-aside">
        
      </li>
  </ul>
  <hr>
</div>
          <div role="main">
            <div class="section">
              <p>Hooks (also known as callbacks or lifecycle events), are functions which are called before and after calls in sequelize are executed. For example, if you want to always set a value on a model before saving it, you can add a <code>beforeUpdate</code> hook.</p>
<h2 id="order-of-operations">Order of Operations</h2>
<pre><code>(1) 
  beforeBulkCreate(daos, fields, fn) 
  beforeBulkDestroy(daos, fields, fn) 
  beforeBulkUpdate(daos, fields, fn)
(2) 
  beforeValidate(dao, fn)
(-)
  validate
(3) 
  afterValidate(dao, fn)
(4) 
  beforeCreate(dao, fn)
  beforeDestroy(dao, fn)
  beforeUpdate(dao, fn)
(-) 
  create 
  destroy 
  update
(5) 
  afterCreate(dao, fn) 
  afterDestroy(dao, fn)
  afterUpdate(dao, fn) 
(6) 
  afterBulkCreate(daos, fields, fn) 
  afterBulkDestory(daos, fields, fn) 
  afterBulkUpdate(daos, fields, fn)
</code></pre>
<h2 id="declaring-hooks">Declaring Hooks</h2>
<p>There are currently three ways to programmatically add hooks. A hook function always runs asynchronousĺy, and can be resolved either by calling a callback (passed as the last argument),
or by returning a promise.</p>
<pre><code class="language-js">// Method 1 via the .define() method
var User = sequelize.define('User', {
  username: DataTypes.STRING,
  mood: {
    type: DataTypes.ENUM,
    values: ['happy', 'sad', 'neutral']
  }
}, {
  hooks: {
    beforeValidate: function(user, fn) {
      user.mood = 'happy'
      fn(null, user)
    },
    afterValidate: function(user, fn) {
      user.username = 'Toni'
      fn(null, user)
    }
  }
})

// Method 2 via the .hook() method
var User = sequelize.define('User', {
  username: DataTypes.STRING,
  mood: {
    type: DataTypes.ENUM,
    values: ['happy', 'sad', 'neutral']
  }
})

User.hook('beforeValidate', function(user, fn) {
  user.mood = 'happy'
  fn(null, user)
})

User.hook('afterValidate', function(user) {
  return sequelize.Promise.reject("I'm afraid I can't let you do that!")
})

// Method 3 via the direct method
var User = sequelize.define('User', {
  username: DataTypes.STRING,
  mood: {
    type: DataTypes.ENUM,
    values: ['happy', 'sad', 'neutral']
  }
})

User.beforeValidate(function(user) {
  user.mood = 'happy'
  return sequelize.Promise.resolve(user)
})

User.afterValidate(function(user, fn) {
  user.username = 'Toni'
  fn(null, user)
})
</code></pre>
<h3 id="instance-hooks">Instance hooks</h3>
<p>The following hooks will emit whenever you're editing a single object...</p>
<pre><code>beforeValidate
afterValidate
beforeCreate / beforeUpdate  / beforeDestroy
afterCreate / afterUpdate / afterDestroy
</code></pre>
<pre><code class="language-js">// ...define ...
User.beforeCreate(function(user, fn) {
  if (user.accessLevel &gt; 10 &amp;&amp; user.username !== "Boss") {
    return fn("You can't grant this user an access level above 10!")
 }
 return fn()
})
</code></pre>
<p>This example will emit an error:</p>
<pre><code class="language-js">User.create({username: 'Not a Boss', accessLevel: 20}).error(function(err) {
  console.log(err) // You can't grant this user an access level above 10!
})
</code></pre>
<p>The following example would emit a success event:</p>
<pre><code class="language-js">User.create({username: 'Boss', accessLevel: 20}).success(function(user) {
  console.log(user) // user object with username as Boss and accessLevel of 20
})
</code></pre>
<h3 id="model-hooks">Model hooks</h3>
<p>Sometimes you'll be editing more than one record at a time by utilizing the <code>bulkCreate, update, destroy</code> methods on the model. The following will emit whenever you're using one of those methods.</p>
<pre><code>beforeBulkCreate / beforeBulkUpdate / beforeBulkDestroy
afterBulkCreate / afterBulkUpdate / afterBulkDestroy
</code></pre>
<p>If you want to emit hooks for each individual record, along with the bulk hooks you can pass <code>individualHooks: true</code> to the call.</p>
<pre><code class="language-js">Model.destroy({accessLevel: 0}, {individualHooks: true}) 
// Will select all records that are about to be deleted and emit before- + after- Destroy on each instance

Model.update({username: 'Toni'}, {accessLevel: 0}, {individualHooks: true})
// Will select all records that are about to be updated and emit before- + after- Update on each instance

Model.bulkCreate({accessLevel: 0}, null, {individualHooks: true}) 
// Will select all records that are about to be deleted and emit before- + after- Create on each instance
</code></pre>
<p>Some model hooks have two or three parameters sent to each hook depending on it's type.</p>
<pre><code class="language-js">Model.beforeBulkCreate(function(records, fields, fn) {
  // records = the first argument sent to .bulkCreate
  // fields = the second argument sent to .bulkCreate
})

Model.bulkCreate([
  {username: 'Toni'}, // part of records argument
  {username: 'Tobi'} // part of records argument
], ['username'] /* part of fields argument */)

Model.beforeBulkUpdate(function(attributes, where, fn) {
  // attributes = first argument sent to Model.update
  // where = second argument sent to Model.update
})

Model.update({gender: 'Male'} /*attributes argument*/, {username: 'Tom'} /*where argument*/)

Model.beforeBulkDestroy(function(whereClause, fn) {
  // whereClause = first argument sent to Model.destroy
})

Model.destroy({username: 'Tom'} /*whereClause argument*/)
</code></pre>
<h2 id="associations">Associations</h2>
<p>For the most part hooks will work the same for instances when being associated except a few things</p>
<ol>
<li>When using add/set[s] functions the beforeUpdate/afterUpdate hooks will run.</li>
<li>The only way to call beforeDestroy/afterDestroy hooks are on associations with <code>onDelete: 'cascade'</code> and the option <code>hooks: true</code>. For instance:</li>
</ol>
<pre><code class="language-js">var Projects = sequelize.define('Projects', {
  title: DataTypes.STRING
})

var Tasks = sequelize.define('Tasks', {
  title: DataTypes.STRING
})

Projects.hasMany(Tasks, {onDelete: 'cascade', hooks: true})
Tasks.belongsTo(Projects)
</code></pre>
<p>This code will run beforeDestroy/afterDestroy on the Tasks table. Sequelize, by default, will try to optimize your queries as much as possible. 
When calling cascade on delete, Sequelize will simply execute a </p>
<pre><code class="language-sql">DELETE FROM `table` WHERE associatedIdentifiier = associatedIdentifier.primaryKey
</code></pre>
<p>However, adding <code>hooks: true</code> explicitly tells Sequelize that optimization is not of your concern and will perform a <code>SELECT</code> on the associated objects and destroy each instance one by one in order to be able to call the hooks with the right parameters.</p>
<h2 id="a-note-about-transactions">A Note About Transactions</h2>
<p>Note that many model operations in Sequelize allow you to specify a transaction in the options parameter of the method. If a transaction <em>is</em> specified in the original call, it will be present in the options parameter passed to the hook function. For example, consider the following snippet:</p>
<pre><code class="language-js">// Here we use the promise-style of async hooks rather than
// the callback.
User.hook('afterCreate', function(user, options) {
  // 'trans' will be available in options.transaction

  // This operation will be part of the same transaction as the 
  // original User.create call.
  return User.update({
    mood: 'sad'
  }, {
    where: {
      id: user.id
    },
    transaction: options.transaction
  });
});


sequelize.transaction(function(trans) {
  User.create({
    username: 'someguy',
    mood: 'happy'
  }, {
    transaction: trans
  });
});
</code></pre>
<p>If we had not included the transaction option in our call to <code>User.update</code> in the preceding code, no change would have occurred, since our newly created user does not exist in the database until the pending transaction has been committed. </p>
<h3 id="internal-transactions">Internal Transactions</h3>
<p>It is very important to recognize that sequelize may make use of transactions internally for certain operations such as <code>Model.findOrCreate</code>. If your hook functions execute read or write operations that rely on the object's presence in the database, or modify the object's stored values like the example in the preceding section, you should always specify <code>{ transaction: options.transaction }</code>.</p>
<p>If the hook has been called in the process of a transacted operation, this makes sure that your dependent read/write is a part of that same transaction. If the hook is not transacted, you have simply specified <code>{ transaction: null }</code> and can expect the default behaviour.</p>
            </div>
          </div> 
          <footer>
  

  <hr>

  <div role="contentinfo">
    <p>
    <!-- Copyright etc -->
    </p>
  </div>

  Built with <a href="http://www.mkdocs.org">MkDocs</a>, using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
	  
        </div>
      </div>

    </section>

  </div>

<div class="rst-versions" role="note" style="cursor: pointer">
    <span class="rst-current-version" data-toggle="rst-current-version">
        
      <span><a href="/v2/" style="color: #fcfcfc;">« Previous</a></span>
      <span style="margin-left: 15px"><a href="/v2/" style="color: #fcfcfc">Next »</a></span>
    </span>
</div>

</body></html>